/*****************************************************
** Author:
** Date: 2019-11-01
*
*****************************************************/

#include "dnalua.h"
#ifdef OS_LINUX
#include <stdlib.h>
#include <sys/sysinfo.h>
#elif defined(OS_DNA)
#include "dna_os.h"
#include "dna_psm.h"
#endif

/**
 * @brief
 * @param  None
 * @retval None
 */
static int dnalua_reboot(lua_State* l)
{
    lua_log_inf("system reboot...");
#ifdef OS_LINUX
    // exit(-1);
#elif defined(OS_DNA)

#endif
    return 0;
}

static int dnalua_reset(lua_State* l)
{
    lua_log_inf("system reset...");
#ifdef OS_LINUX
    // exit(-1);
#elif defined(OS_DNA)

#endif
    return 0;
}

static int dnalua_boottype(lua_State* l)
{
    int boottype;
#ifdef OS_LINUX
    boottype = 0;
#elif defined(OS_DNA)
    boottype = dna_reboot_reason();
#endif
    lua_log_inf("boottype %d", boottype);
    lua_pushinteger(l, boottype);
    return 1;
}

static int dnalua_network(lua_State* l)
{
    int network;
#ifdef OS_LINUX
    network = 0;
#elif defined(OS_DNA)
    network = dna_network_status_get();
#endif
    lua_log_inf("network %d", network);
    lua_pushinteger(l, network);
    return 1;
}

static int dnalua_rssi(lua_State* l)
{
    char rssi;
#ifdef OS_LINUX
    rssi = 0;
#elif defined(OS_DNA)
    dna_wlan_get_current_rssi(&rssi);
#endif
    lua_log_inf("rssi %d", rssi);
    lua_pushinteger(l, rssi);
    return 1;
}

static int dnalua_uptime(lua_State* l)
{
    unsigned long uptime;
#ifdef OS_LINUX
    struct sysinfo info;
    if (sysinfo(&info)) {
        lua_log_wrn("failed to get sysinfo");
        uptime = 0;
    }
    else {
        uptime = info.uptime;
    }
#elif defined(OS_DNA)
    uptime = dna_bootup_timestamp() * 1000;
#endif
    lua_log_inf("uptime %lu", uptime);
    lua_pushinteger(l, uptime);
    return 1;
}

static int dnalua_get_mac(lua_State* l)
{
    unsigned char mac[6];
#ifdef OS_LINUX
    memset(mac, 0x0, sizeof(mac));
#elif defined(OS_DNA)
    dna_wlan_get_mac_address(mac);
#endif
    dump_memory("mac", mac, sizeof(mac));
    lua_arch_pushtable(l, mac, sizeof(mac));
    return 1;
}

static int dnalua_kv_write(lua_State* l)
{
    int  intval, type, valsize = 0;
    char *strval;
    void *val;

    char *k = luaL_checkstring(l, -2);
    lua_log_dbg("get k(%d):%s", -2, k);

    switch (type = lua_type(l, -1)) {
        case LUA_TBOOLEAN:
        case LUA_TNUMBER:
            intval = lua_toboolean(l, -1);
            lua_log_dbg("get %s(%d) %d", lua_typename(l, type), -1, intval);
            val = (void *)&intval;
            valsize = sizeof(int);
            break;
        case LUA_TSTRING:
            strval = (char *)lua_tostring(l, -1);
            lua_log_dbg("get %s(%d):%s", lua_typename(l, type), -1, strval);
            val = (void *)strval;
            valsize = strlen(strval);
            break;
        default:
            lua_log_wrn("unknow type %d", type);
            return 0;
    }

    lua_log_inf("set k:%s vsize %d", k, valsize);
#ifdef OS_LINUX

#elif defined(OS_DNA)
    dna_psm_set_keyvalue(DNA_PSM_RESET_ABLE_ERASE, k, val, valsize);
#endif
    return 0;
}

static int dnalua_kv_read(lua_State* l)
{
    unsigned char val[256];
    int valsize = 0, intval;

    char *k = luaL_checkstring(l, -1);
    lua_log_dbg("get k(%d):%s", -1, k);

#ifdef OS_LINUX

#elif defined(OS_DNA)
    valsize = dna_psm_get_keyvalue(DNA_PSM_RESET_ABLE_ERASE, k, val, sizeof(val));
#endif
    if (valsize != sizeof(int) && valsize != 0) {   // we think this is string
        lua_pushstring(l, val);
    }
    else {
        intval = *(int *)val;
        lua_pushinteger(l, intval);
    }

    lua_log_inf("get k:%s vsize %d", k, valsize);
    return 1;
}

static int dnalua_kv_earse(lua_State* l)
{
    char *k = luaL_checkstring(l, -1);
    lua_log_dbg("get k(%d):%s", -1, k);

    lua_log_inf("del k:%s", k);
#ifdef OS_LINUX

#elif defined(OS_DNA)
    dna_psm_del_keyvalue(DNA_PSM_RESET_ABLE_ERASE, k);
#endif
    return 0;
}

static int dnalua_cloud_upload(lua_State* l)
{
    int type;
    if ((type = lua_type(l, -4)) != LUA_TNUMBER) {
        lua_log_wrn("cloudid type %s err", lua_typename(l, type));
        return 0;
    }
    int cld_id = luaL_checkinteger(l, -4);

    if ((type = lua_type(l, -3)) != LUA_TNUMBER) {
        lua_log_wrn("cld_type type %s err", lua_typename(l, type));
        return 0;
    }
    int cld_type = luaL_checkinteger(l, -3);

    if ((type = lua_type(l, -2)) != LUA_TNUMBER) {
        lua_log_wrn("cld_mode type %s err", lua_typename(l, type));
        return 0;
    }
    int cld_mode = luaL_checkinteger(l, -2);

    char *cld_kv = NULL;
    switch (type = lua_type(l, -1)) {
        case LUA_TSTRING:
            cld_kv = luaL_checkstring(l, -1);
            break;
        default:
            lua_log_wrn("cld_data type %s not support", lua_typename(l, type));
            return 0;
    }

    int cld_kvlen = strlen(cld_kv);
    lua_log_dbg("cld id %d type %d mode %d kvlen %d kv %s", cld_id, cld_type, cld_mode, cld_kvlen, cld_kv);
    // int ret = dna_cloud_data_upload(cld_id, cld_type, cld_mode, cld_kv, cld_kvlen);
    // lua_log_dbg("cloud_data_upload ret %d", ret);
    return 0;
}

static int dnalua_get_snapshot(lua_State* l)
{
    int snapsize;
    char *snapshot = lua_arch_get_snapshot(&snapsize);
    if (snapshot == NULL || snapsize == 0) {
        lua_log_err("get snapshot %p snapsize %d failed", snapshot, snapsize);
        lua_pushnil(l);
    }
    else {
        lua_log_dbg("push snapshot %d:%s", snapsize, snapshot);
        lua_pushstring(l, snapshot);
    }
    return 1;
}

int luaopen_dnalua(lua_State *l)
{
    const char *lib_name = "dnalua";
    luaL_Reg dnalua[] = {
        {"reboot",      dnalua_reboot},
        {"reset",       dnalua_reset},
        {"boottype",    dnalua_boottype},
        {"network",     dnalua_network},
        {"rssi",        dnalua_rssi},
        {"uptime",      dnalua_uptime},
        {"get_mac",     dnalua_get_mac},
        {"kv_write",    dnalua_kv_write},
        {"kv_read",     dnalua_kv_read},
        {"kv_earse",    dnalua_kv_earse},
        {"cloud_upload", dnalua_cloud_upload},
        {"get_snapshot", dnalua_get_snapshot},
        {"PORT_ID_BL",  NULL},
        {"PORT_ID_HI",  NULL},
        {"PORT_ID_NONE", NULL},
        {"PORT_ID_UART", NULL},
        {"PORT_ID_I2C",  NULL},
        {"CLOUD_DEVDATA_BINARY",  NULL},
        {"CLOUD_DEVDATA_KEYVALUE",  NULL},
        {"CLOUD_DEVDATA_PASSTHROUGH",  NULL},
        {"CLOUD_PERIOD_UPLOAD",  NULL},
        {"CLOUD_TRIGGER_UPLOAD", NULL},
        {"CLOUD_ACTIVE_UPLOAD",  NULL},
        {NULL, NULL},
    };
    luaL_openlib(l, lib_name, dnalua, 0);
    print_lua_stack(l, "open lua 'dnalua'");

    lua_pushinteger(l, PORT_ID_BL);
    lua_setfield(l, -2, "PORT_ID_BL");
    lua_pushinteger(l, PORT_ID_HI);
    lua_setfield(l, -2, "PORT_ID_HI");

    lua_pushinteger(l, PORT_ID_NONE);
    lua_setfield(l, -2, "PORT_ID_NONE");
    lua_pushinteger(l, PORT_ID_UART);
    lua_setfield(l, -2, "PORT_ID_UART");
    lua_pushinteger(l, PORT_ID_I2C);
    lua_setfield(l, -2, "PORT_ID_I2C");

    lua_pushinteger(l, CLOUD_DEVDATA_BINARY);
    lua_setfield(l, -2, "CLOUD_DEVDATA_BINARY");
    lua_pushinteger(l, CLOUD_DEVDATA_KEYVALUE);
    lua_setfield(l, -2, "CLOUD_DEVDATA_KEYVALUE");
    lua_pushinteger(l, CLOUD_DEVDATA_PASSTHROUGH);
    lua_setfield(l, -2, "CLOUD_DEVDATA_PASSTHROUGH");

    lua_pushinteger(l, CLOUD_PERIOD_UPLOAD);
    lua_setfield(l, -2, "CLOUD_PERIOD_UPLOAD");
    lua_pushinteger(l, CLOUD_TRIGGER_UPLOAD);
    lua_setfield(l, -2, "CLOUD_TRIGGER_UPLOAD");
    lua_pushinteger(l, CLOUD_ACTIVE_UPLOAD);
    lua_setfield(l, -2, "CLOUD_ACTIVE_UPLOAD");

    lua_log_inf("open lua 'dnalua' success");
    return LUA_ARCH_OK;
}

int luaclose_dnalua(lua_State *l)
{
    lua_log_inf("close lua 'dnalua'");
    return LUA_ARCH_OK;
}

/* End of file */



